//% require easeljs.min.js

//% extends Element

function Game( tag, list )
{
    if( tag.tagName.toLowerCase() != "canvas" )
    {
        throw "Game must be put in a canvas.";
    }
    this.Super( tag );
    
    var stage = new Stage(tag);

    function genSlot( ){  
        this.shortSignal.apply( this, arguments ); 
    }
    
    for( var k in list )
    {
        this[k] = bind( genSlot, list[k] );
        this.addSlot(k);
    }
    
    var nextState = null;
    var state = null;
    var reset = false;
    var states = {};

    this.fps = 30;
    
    this.addChild = function( c )
    {
        this.Element.addChild( c );
        if( c instanceof Controller && c.getDisplayObject() )
        {
            stage.addChild( c.getDisplayObject() );
        }
    };
    
    this.removeChild = function( c )
    {
        this.Element.removeChild( c );
        if( c instanceof Controller && c.getDisplayObject() )
        {
            stage.removeChild( c.getDisplayObject() );
        }
    };

    var onEnterFrame = thisBind( this, function ()
    {
        if( nextState != state )
        {
            if( reset || !states[nextState] )
            {
                var C = getClass(nextState);
                states[ nextState ] = new C();
            }
            
            this.addChild( states[nextState] );
            if( state )
            {
                states[ state ].message("onExitState");
            }
            states[ nextState ].message("onEnterState");
            
            this.removeChild( states[state] );
            state = nextState;
        }
        
        this.shortSignal( "onTick", 1/this.fps );
        
        stage.update();
        efcb = setTimeout( onEnterFrame, 1000/this.fps );
    });
    
    var efcb = setTimeout( onEnterFrame, 1000/this.fps );

    //% slot
    this.destruct = function(){
        this.Controller.destruct();
        clearTimeout(efcb);
        efcb = null;
    };
    
    this.set = function(s){
        nextState = s;
        reset = false;
    };
    
    this.reset = function(s){
        nextState = s;
        reset = true;
    };
    
    this.message("onGameReady");
}